﻿

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdint>  // 添加对 std::int64_t 的支持

//观察者模式优点：
//
//解耦（被观察者不需要关心观察者的具体实现逻辑）
//动态扩展方便（随时新增 / 移除观察者）


//总结:
//如果系统里“群主和群员的关系经常变动”需要经常添加和移除，并且群员的更新状态的处理逻辑很多样，观察者模式更合适。
//如果系统规模很小，成员固定，逻辑简单，直接调用反而更直观，没必要引入观察者模式。

//class GroupOwner {
//	std::vector<Observer*> members;
//public:
//	void notify(const std::string& msg) {
//		for (auto* m : members) {
//			m->update(msg);  //群主直接调用成员方法
//		}
//	}
//};

//使用观察者模式的实现
//群主（Subject）只管发消息，谁订阅了群主就能收到消息。
//
//优点:
//1.解耦：群主不需要知道群里有谁，也不用关心每个成员的处理逻辑。
//2.群主只管“发通知”，成员自己处理收到的消息。
//3.扩展性好：新成员入群只需 attach()，退群就 detach()，而群主类的代码完全不用改。
//4.符合开闭原则：新增不同类型的观察者（比如“自动翻译机器人”“消息转发机器人”）则无需修改群主代码。
//5.职责单一：群主的职责是“发布消息”，成员的职责是“接收并处理消息”，逻辑清晰。


// ====================== 抽象观察者 ======================
// 观众抽象接口：定义一个 update() 方法
// 所有的观察者都必须实现这个方法，来响应 打喷嚏人(被观察者) 的状态变化
class Observer {
public:

	//纯虚函数：子类必须实现
	virtual void update(const std::string& message) = 0;

	//虚析构函数：保证子类析构时正确调用
	virtual ~Observer() = default;
};

//“一个人打喷嚏，周围的多个人都收到了通知并各自做出反应Go away。”

// ====================== 被观察者（主题）/ 群主 ======================
// Subject 维护一个观察者(观众)列表，并在状态变化时通知它们
class Subject {

	std::vector<Observer*> observers;  //维护一个多种观察者类型的观察者列表
	std::string _newState;			   //被观察者的当前状态

public:
	//增加一个观众, 添加观察者（订阅）,多一个观众订阅了通知
	void attach(Observer* obs) {
		observers.push_back(obs);
	}

	//移除某一个观察者（退订）
	void detach(Observer* obs) {
		observers.erase(
			std::remove(observers.begin(), observers.end(), obs),
			observers.end()
		);
	}

	//修改 被观察者(打喷嚏人)的 状态，并通知所有观察者
	void setState(const std::string& newState) {
		_newState = newState;
		notify();	//通知所有观察者
	}
private:

	//通知所有观察者（并调用它们的 update 方法更新状态）
	void notify() {
		for (auto* obs : observers) {
			if (obs)
			{
				//添加空指针检查
				obs->update(_newState);
			}
		}
	}
};


// ====================== 具体的观察者(观众) ======================
// 继承 Observer，当 打喷嚏的人 通知时，执行 update()
class ConcreteObserver : public Observer {

	std::string name;  //每个观察者有个名字，用于标识

	std::int64_t Id;   //每个观察者的Id

public:

	/// <summary>
	/// 构造函数：传入观察者的名字
	/// </summary>
	/// <param name="n"></param>
	ConcreteObserver(const std::string& n, std::int64_t id) : name(n), Id(id) {}

	/// <summary>
	/// 根据 被观察者的状态 更新 观众的状态
	/// </summary>
	/// <param name="message"></param>
	void update(const std::string& message) override {

		if (message == "胜利")
		{
			std::cout << "观察者 " << name << " 收到更新: " << "胜利了, 非常开心!" << std::endl;
		}
		else if (message == "失败")
		{
			std::cout << "观察者 " << name << " 收到更新: " << "失败了, 不开心!" << std::endl;
		}
		else {

			std::cout << "观察者 " << name << " 收到更新: " << "非法状态!" << std::endl;
		}

	}
};



// ====================== 具体的观察者(观众) ======================
// 继承 Observer，当 打喷嚏的人 通知时，执行 update()
class ConcreteObserverB : public Observer {

	std::string name;  //每个观察者有个名字，用于标识

	std::int64_t Id;   //每个观察者的Id

public:

	/// <summary>
	/// 构造函数：传入观察者的名字
	/// </summary>
	/// <param name="n"></param>
	ConcreteObserverB(const std::string& n, std::int64_t id) : name(n), Id(id) {}

	/// <summary>
	/// 根据 被观察者的状态 更新 观众的状态
	/// </summary>
	/// <param name="message"></param>
	void update(const std::string& message) override {

		if (message == "胜利")
		{
			std::cout << "观察者 " << name << " 收到更新: " << "胜利了, 旺旺旺叫!" << std::endl;
		}
		else if (message == "失败")
		{
			std::cout << "观察者 " << name << " 收到更新: " << "失败了, 灰溜溜走开!" << std::endl;
		}
		else {
			std::cout << "观察者 " << name << " 收到更新: " << "非法状态!" << std::endl;
		}
	}
};



int main()
{
	Subject subject;
	ConcreteObserver obs1("张三", 1);
	ConcreteObserver obs2("李四", 2);
	ConcreteObserver obs3("王五", 3);

	subject.attach(&obs1);
	subject.attach(&obs2);
	subject.attach(&obs3);

	subject.setState("胜利");

	subject.setState("失败");

	subject.setState("未知状态");

	subject.detach(&obs2);  //移除"李四"
	subject.detach(&obs3);  //移除"王五"

	ConcreteObserverB obs4("小狗", 8);
	subject.attach(&obs4);

	subject.setState("胜利");

	subject.setState("失败");

	std::cout << "程序结束!\n";
}

